package com.ai.sevice.ai;

import com.ai.common.email.EmailClient;
import com.ai.common.enums.ConfigModuleEnum;
import com.ai.common.enums.OptionTypeEnum;
import com.ai.common.enums.QAEnum;
import com.ai.common.gpt.ChatroomUtil;
import com.ai.common.gpt.OpenAiWebClient;
import com.ai.common.gpt.subscriber.OpenAIChatRoomSubscriber;
import com.ai.common.gpt.subscriber.OpenAIMessageResponse;
import com.ai.common.gpt.subscriber.OpenAISubscriber;
import com.ai.common.http.SubscriberImpl;
import com.ai.common.http.TransferStationClient;
import com.ai.common.utils.*;
import com.ai.dao.entity.ai.AiDynamic;
import com.ai.dao.entity.ai.AiUserAccessRecord;
import com.ai.repository.ai.AiDynamicRepository;
import com.ai.repository.ai.AiUserAccessRecordRepository;
import com.ai.sevice.ai.remote.Choice;
import com.ai.sevice.ai.remote.CompletionsRequest;
import com.ai.sevice.ai.remote.CompletionsResponse;
import com.ai.sevice.ai.remote.Message;
import com.ai.sevice.ai.request.*;
import com.ai.sevice.ai.response.*;
import com.ai.sevice.ai.request.dto.GptRequestMessageDto;
import com.ai.sevice.ai.response.dto.*;
import com.ai.sevice.config.response.dto.AiCardDto;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author ：shengwenyang
 * @date ：Created in 2023/4/18 11:01
 * @description：
 * @version:
 */
@Slf4j
@Service
public class GptService {

    @Autowired
    private OpenAiWebClient openAiWebClient;
    @Autowired
    private AiUserAccessRecordRepository aiUserAccessRecordRepository;
    @Autowired
    private EmailClient emailClient;
    @Autowired
    private TransferStationClient transferStationClient;
    @Autowired
    private AiDynamicRepository aiDynamicRepository;

    /**
     * ai接口
     * @param request
     * @return
     */
    public AiResponse ai(ChatroomRequest request) {
        AiResponse response = new AiResponse();
        if (StringUtils.isBlank(request.getContent())){
            response.setCode(1);
            response.setMsg("内容不能为空");
            return response;
        }
        if (request.getContent().length() > 2000){
            response.setCode(1);
            response.setMsg("内容最多2000个字");
            return response;
        }
        if (request.getDescribe() == null){
            request.setDescribe("");
        }
        if (OptionTypeEnum.translate.getValue().equals(request.getOptionType())){
            //翻译逻辑处理
            if (StringUtils.isBlank(request.getDescribe())){
                response.setCode(1);
                response.setMsg("请输入需要翻译的语言");
                return response;
            }
        }
        String content = request.getContent();
        String aiAssembly = ConfigUtil.getInstance().getConfig(ConfigModuleEnum.aiAssembly.getModule(), request.getOptionType());
        if (StringUtils.isNotBlank(aiAssembly)){
            content = aiAssembly.replace("[describe]",request.getDescribe()).replace("[content]",request.getContent());
        }

        CompletionsResponse completionsResponse = getCompletionsResponse(content);
        if (completionsResponse != null && CollectionUtils.isNotEmpty(completionsResponse.getChoices())) {
            Choice choice = completionsResponse.getChoices().get(0);
            response.setContent(choice.getMessage().getContent());
        }
        return response;
    }

    public CompletionsResponse getCompletionsResponse(String content) {
        String isTransferStation = ConfigUtil.getInstance().getConfig(ConfigModuleEnum.DEFAULT.getModule(),"isTransferStationOpenAi");
        CompletionsResponse completionsResponse;
        if (StringUtils.isNotBlank(isTransferStation) && isTransferStation.equals("true")){
            //接口中转
            CompletionsRequest completionsRequest = new CompletionsRequest();
            //completionsRequest.setModel("gpt-3.5-turbo");
//            completionsRequest.setModel("gpt-3.5-turbo-16k-0613");
//            completionsRequest.setModel("gpt-3.5-turbo-0613");
            completionsRequest.setModel("gpt-3.5-turbo-1106");
            completionsRequest.setMax_tokens(null);
            completionsRequest.setTemperature(new BigDecimal("0.5"));
            completionsRequest.setFrequency_penalty(new BigDecimal("0"));
            completionsRequest.setPresence_penalty(new BigDecimal("0"));
            completionsRequest.setMessages(Arrays.asList(new Message("user",content)));
            completionsResponse = transferStationClient.completions(completionsRequest, TokenUtil.pollChatGptToken());
//            completionsResponse = transferStationClient.completions(completionsRequest, "Bearer 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");
        }else {
            completionsResponse = openAiWebClient.chatCompletions(content);
        }
        return completionsResponse;
    }

    /**
     * 聊天接口
     * @param request
     * @return
     */
    public ChatroomResponse chatroom(ChatroomRequest request) {
        String uid = TraceContext.getCurrent().getTag("uid", String.class);
        ChatroomResponse response = new ChatroomResponse();
        if (StringUtils.isBlank(uid) || StringUtils.isBlank(request.getContent())){
            response.setCode(1);
            response.setMsg("请求参数有误");
            return response;
        }
        if (request.getContent().length() > 500){
            response.setCode(1);
            response.setMsg("消息最多500个字");
            return response;
        }

        //添加消息
        ChatroomUtil.addUserMessage(uid,request.getContent(), QAEnum.question.getValue());
        //获取历史记录
        String userMessage = ChatroomUtil.getUserMessage(uid);

        CompletionsResponse completionsResponse = getCompletionsResponse(userMessage);
        if (completionsResponse != null && CollectionUtils.isNotEmpty(completionsResponse.getChoices())) {
            Choice choice = completionsResponse.getChoices().get(0);
            String content = choice.getMessage().getContent();
            if (StringUtils.isNotBlank(content) && content.length() > 2){
                String first = content.substring(0, 2);
                if (first.equalsIgnoreCase("Q:") || first.equalsIgnoreCase("A:")){
                    content = content.substring(2);
                }
            }
            ChatroomUtil.addUserMessage(uid,content, QAEnum.answer.getValue());
            response.setContent(content);
        }
        return response;
    }

    /**
     * 聊天接口(流式返回)
     * @param request
     * @return
     */
    public Flux<String> chatroomFlux(ChatroomRequest request) {
        String uid = TraceContext.getCurrent().getTag("uid", String.class);
        if (StringUtils.isBlank(uid) || StringUtils.isBlank(request.getContent())){
            return  Flux.just(JSON.toJSONString(new OpenAIMessageResponse("请求参数有误", null)),JSON.toJSONString(new OpenAIMessageResponse("", true)));
        }
//        if (request.getContent().length() > 100){
//            return  Flux.just(JSON.toJSONString(new OpenAIMessageResponse("内容最多100个字", null)),JSON.toJSONString(new OpenAIMessageResponse("", true)));
//        }
        //获取历史记录
        ChatroomUtil.addUserMessage(uid,request.getContent(), QAEnum.question.getValue());
        String userMessage = ChatroomUtil.getUserMessage(uid);
        return Flux.create(emitter -> {
            OpenAIChatRoomSubscriber subscriber = new OpenAIChatRoomSubscriber(emitter,uid);
            Flux<String> openAiResponse = openAiWebClient.getChatResponse(uid, userMessage, null, new BigDecimal("0.5"), null);
            openAiResponse.subscribe(subscriber);
            emitter.onDispose(subscriber);
        });
    }

    /**
     * 聊天接口(流式返回)
     * @param content
     * @return
     */
    public Flux<String> chatroomFluxGet(String uid,String content) {
        log.info("/gpt/chatroomFluxGet：uid -> " + uid + "  content - > " + content);
        if (StringUtils.isBlank(uid) || StringUtils.isBlank(content)){
            return  Flux.just(JSON.toJSONString(new OpenAIMessageResponse("请求参数有误", null)),JSON.toJSONString(new OpenAIMessageResponse("", true)));
        }
        CompletionsRequest request = new CompletionsRequest();
        request.setModel("gpt-3.5-turbo");
        request.setTemperature(new BigDecimal("0.5"));
        request.setFrequency_penalty(new BigDecimal("0"));
        request.setPresence_penalty(new BigDecimal("0"));
        request.setMessages(Arrays.asList(new Message("user",content)));
        return Flux.create(emitter -> {
            SubscriberImpl subscriber = new SubscriberImpl(emitter);
            Flux<String> openAiResponse = transferStationClient.completionsFlux(request,TokenUtil.pollChatGptToken());
            openAiResponse.subscribe(subscriber);
            emitter.onDispose(subscriber);
        });
    }

    /**
     * 获取用户聊天记录
     * @param userId
     * @return
     */
    public GetChatHistoryResponse getChatHistory(String userId) {
        GetChatHistoryResponse response = new GetChatHistoryResponse();
        String userMessage = ChatroomUtil.getUserMessage(userId);
        response.setChatHistory(userMessage);
        return response;
    }

    /**
     * 清空用户聊天记录
     * @param userId
     * @return
     */
    public ClearChatHistoryResponse clearChatHistory(String userId) {
        ClearChatHistoryResponse response = new ClearChatHistoryResponse();
        try {
            ChatroomUtil.deleteUserMessage(userId);
            response.setResult(true);
        }catch (Exception e){
            response.setResult(false);
            log.error("clearChatHistory",e);
        }
        return response;
    }

    /**
     * 获取用户访问记录
     * @param request
     * @return
     */
    public GetUserCallOnHistoryResponse getUserCallOnHistory(GetUserCallOnHistoryRequest request) {
        GetUserCallOnHistoryResponse response = new GetUserCallOnHistoryResponse();

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        AiUserAccessRecord aiUserAccessRecordRequest = new AiUserAccessRecord();
        aiUserAccessRecordRequest.setUid(request.getUid());
        aiUserAccessRecordRequest.setOptionType(request.getOptionType());
        aiUserAccessRecordRequest.setIsDelete(0);
        String superAdmin = ConfigUtil.getInstance().getConfig(ConfigModuleEnum.DEFAULT.getModule(), "superAdmin");
        boolean flag = false;
        List<AiUserAccessRecord> aiUserAccessRecordList = null;
        if (StringUtils.isNotBlank(superAdmin)) {
            String[] superAdminArr = superAdmin.split(",");
            List<String> superAdminList = new ArrayList<>(superAdminArr.length);
            //数组转list
            Collections.addAll(superAdminList, superAdminArr);
            if (superAdminList.contains(request.getUid())){
                flag = true;
                aiUserAccessRecordList = aiUserAccessRecordRepository.getUserCallOnHistoryByType(aiUserAccessRecordRequest);
            }else{
                aiUserAccessRecordList = aiUserAccessRecordRepository.getUserCallOnHistory(aiUserAccessRecordRequest);
            }
        }else{
            aiUserAccessRecordList = aiUserAccessRecordRepository.getUserCallOnHistory(aiUserAccessRecordRequest);
        }
        if (CollectionUtils.isEmpty(aiUserAccessRecordList)){
            return response;
        }
        PageInfo<AiUserAccessRecord> pageInfo = new PageInfo<>(aiUserAccessRecordList);
        response.setTotal(pageInfo.getTotal());
        List<UserCallOnHistoryDto> list = new ArrayList<>();
        for (AiUserAccessRecord aiUserAccessRecord : aiUserAccessRecordList){
            UserCallOnHistoryDto userCallOnHistoryDto = new UserCallOnHistoryDto();
            userCallOnHistoryDto.setId(aiUserAccessRecord.getId());
            userCallOnHistoryDto.setDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(aiUserAccessRecord.getDateTime()));
            if (aiUserAccessRecord.getRequest() != null) {
                UserCallOnHistoryRequestDto userCallOnHistoryRequestDto = JSON.parseObject(aiUserAccessRecord.getRequest(), UserCallOnHistoryRequestDto.class);
                if (userCallOnHistoryRequestDto != null && userCallOnHistoryRequestDto.getRequest() != null){
                    userCallOnHistoryDto.setUserContent(getUserContent(aiUserAccessRecord.getOptionType(),userCallOnHistoryRequestDto.getRequest().getContent(),userCallOnHistoryRequestDto.getRequest().getDescribe()));
                    if (flag){
                        userCallOnHistoryDto.setUserContent(aiUserAccessRecord.getUid() + " -> " + userCallOnHistoryDto.getUserContent());
                    }
                }
            }
            if (aiUserAccessRecord.getResponse() != null) {
                ContentDto contentDto = JSON.parseObject(aiUserAccessRecord.getResponse(), ContentDto.class);
                if (contentDto != null){
                    userCallOnHistoryDto.setSystemContent(contentDto.getContent());
                }
            }
            list.add(userCallOnHistoryDto);
        }
        response.setList(list);
        return response;
    }

    //获取用户内容
    private String getUserContent(String optionType,String content,String describe){
        if (StringUtils.isBlank(content) || StringUtils.isBlank(optionType)){
            return content;
        }
        //翻译处理
        if (OptionTypeEnum.translate.getValue().equals(optionType) && StringUtils.isNotBlank(describe)){
            content = describe + "翻译 -> " + content;
        }
        return content;
    }

    /**
     * 删除用户访问记录
     * @return
     */
    public DeleteUserCallOnHistoryResponse deleteUserCallOnHistory(Long id) {
        DeleteUserCallOnHistoryResponse response = new DeleteUserCallOnHistoryResponse();
        String uid = TraceContext.getCurrent().getTag("uid", String.class);
        if (StringUtils.isBlank(uid)){
            response.setCode(1);
            response.setMsg("uid不能为空");
            return response;
        }
        AiUserAccessRecord userCallOnHistory = aiUserAccessRecordRepository.getUserCallOnHistory(id);
        if (userCallOnHistory == null || userCallOnHistory.getIsDelete() == 1 || !uid.equals(userCallOnHistory.getUid())){
            response.setCode(1);
            response.setMsg("记录不存在");
            return response;
        }
        AiUserAccessRecord aiUserAccessRecord = new AiUserAccessRecord();
        aiUserAccessRecord.setId(id);
        aiUserAccessRecord.setIsDelete(1);
        int update = aiUserAccessRecordRepository.updateByPrimaryKeySelective(aiUserAccessRecord);
        if (update <= 0){
            response.setCode(1);
            response.setMsg("删除失败");
            return response;
        }
        return response;
    }

    /**
     * 获取用户访问记录详情
     * @return
     */
    public GetUserCallOnHistoryDetailResponse getUserCallOnHistoryDetail(Long id) {
        GetUserCallOnHistoryDetailResponse response = new GetUserCallOnHistoryDetailResponse();
        AiUserAccessRecord userCallOnHistory = aiUserAccessRecordRepository.getUserCallOnHistory(id);
        if (userCallOnHistory != null && userCallOnHistory.getIsDelete() == 0){
            UserCallOnHistoryRequestDto userCallOnHistoryRequestDto = JSON.parseObject(userCallOnHistory.getRequest(), UserCallOnHistoryRequestDto.class);
            if (userCallOnHistoryRequestDto != null && userCallOnHistoryRequestDto.getRequest() != null){
                response.setUserContent(getUserContent(userCallOnHistory.getOptionType(),userCallOnHistoryRequestDto.getRequest().getContent(),userCallOnHistoryRequestDto.getRequest().getDescribe()));
            }
            if (userCallOnHistory.getResponse() != null) {
                ContentDto contentDto = JSON.parseObject(userCallOnHistory.getResponse(), ContentDto.class);
                if (contentDto != null){
                    response.setSystemContent(contentDto.getContent());
                }
            }
            response.setDateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(userCallOnHistory.getDateTime()));
        }
        return response;
    }

    ////////////////////////////////////////////////////////////////////////
    public Flux<String> aiFlux(String content){
        try {
            if (content.length() > 500){
                return  Flux.just(JSON.toJSONString(new OpenAIMessageResponse("内容最多500个字", null)),JSON.toJSONString(new OpenAIMessageResponse("", true)));
            }
            FluxBackRequest request = new FluxBackRequest();
            //request.setMax_tokens(new BigDecimal(8000));
            request.setTemperature(new BigDecimal("0.5"));
            GptRequestMessageDto message = new GptRequestMessageDto();
            message.setContent(content);
            message.setRole("user");
            request.setMessages(Collections.singletonList(message));

            return Flux.create(emitter -> {
                OpenAISubscriber subscriber = new OpenAISubscriber(emitter);
                Flux<String> openAiResponse = openAiWebClient.getChatResponse(null, content, request.getMax_tokens(), request.getTemperature(), null);
                openAiResponse.subscribe(subscriber);
                emitter.onDispose(subscriber);
            });
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
        return null;
    }

    /**
     * 获取ai动态列表
     * @param request
     * @return
     */
    public GetAiDynamicListResponse getAiDynamicList(GetAiDynamicListRequest request) {
        GetAiDynamicListResponse response = new GetAiDynamicListResponse();
        if (request.getIsFilter() != null && request.getIsFilter()){
            List<AiDynamicFilterDto> filters = new ArrayList<>();
            filters.add(new AiDynamicFilterDto("","全部精选"));
            filters.add(new AiDynamicFilterDto("programmer","编程"));
            filters.add(new AiDynamicFilterDto("composition","智能作家"));
            response.setFilters(filters);
        }
        PageHelper.startPage(request.getPageNo(), request.getPageSize());
        List<AiDynamic> listDesc = aiDynamicRepository.getListDesc(request.getOptionType(),request.getTitle());
        PageInfo<AiDynamic> pageInfo = new PageInfo<>(listDesc);
        response.setTotal(pageInfo.getTotal());
        if (CollectionUtils.isEmpty(listDesc)){
            return response;
        }
        List<AiDynamicDto> aiDynamicDtoList = new ArrayList<>();
        for (AiDynamic aiDynamic : listDesc){
            AiDynamicDto aiDynamicDto = ConvertUtil.convert(aiDynamic,AiDynamicDto.class);
            if (aiDynamicDto == null){
                continue;
            }
            AiCardDto aiCard = CommonUtil.getAiCardByType(aiDynamicDto.getOptionType());
            if (aiCard != null) {
                aiDynamicDto.setOptionName(aiCard.getTitle());
            }
            if (aiDynamic.getDateTimestamp() != null){
                aiDynamicDto.setDateTime(getDateTime(aiDynamic.getDateTimestamp()));
            }
            aiDynamicDtoList.add(aiDynamicDto);
        }
        response.setList(aiDynamicDtoList);
        return response;
    }
    /**
     * 获取ai动态列表
     * @param request
     * @return
     */
    public GetAiDynamicDetailResponse getAiDynamicDetail(GetAiDynamicDetailRequest request) {
        GetAiDynamicDetailResponse response = new GetAiDynamicDetailResponse();
        AiDynamic aiDynamic = aiDynamicRepository.getAiDynamicById(request.getId());
        response.setTitle(aiDynamic.getTitle());
        response.setSummary(aiDynamic.getSummary());
        response.setOptionType(aiDynamic.getOptionType());
        AiCardDto aiCard = CommonUtil.getAiCardByType(aiDynamic.getOptionType());
        if (aiCard != null) {
            response.setOptionName(aiCard.getTitle());
        }
        response.setContent(aiDynamic.getContent());
        response.setAuthor(aiDynamic.getAuthor());
        if (aiDynamic.getDateTimestamp() != null) {
            response.setDateTime(CommonUtil.getDateTimeStr(aiDynamic.getDateTimestamp()));
        }
        return response;
    }

    private String getDateTime(Long dateTimestamp) {
        if (dateTimestamp == null) {
            return null;
        }
        String dateTime = null;
        Instant instant = Instant.ofEpochMilli(dateTimestamp);
        LocalDateTime time = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(time, now);
        long minutes = duration.toMinutes();
        long hours = duration.toHours();
        if (minutes < 60) {
            if (minutes == 0){
                minutes = 1;
            }
            dateTime = minutes + "分钟前";
        } else if (hours < 24) {
            if (hours == 0){
                hours = 1;
            }
            dateTime = hours + "小时前";
        } else {
            dateTime = CommonUtil.getDateTimeStr(dateTimestamp);
        }
        return dateTime;
    }
}
